﻿using DVM.DB;
using DVM.DV.Factory;
using DVM.DV.Model;
using Miao.Utility.Core;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace DVM.DV.Extensions
{
    public static class FieldExtend
    {


        /// <summary>
        /// 基于特性属性自动赋值
        /// 对标记有JsonPropertyAttribute特性，且参数类型ComField对象值的属性自动赋值
        /// </summary>
        /// <typeparam name="TSource">来源对象类型</typeparam>
        /// <typeparam name="TResult">输出对象类型</typeparam>
        /// <param name="sources">输入参数</param>
        /// <param name="convertFunc">输出对象数据转化委托</param>
        /// <param name="copy">当存在一致属性时，是否Copy内容</param>
        /// <returns></returns>
        public static List<TResult> AutoFieldMapper<TSource, TResult>(this List<TSource> sources,
            Func<TSource, TResult>? convertFunc = null,
            bool copy = true)
            where TSource : class
            where TResult : class, new()
        {
            var result = new List<TResult>();
            var init = CommmonFieldExtend.GetStatic().InitFilterFields(sources, result);
            var sourcePutPropertyDic = init.SourcePropertyInfos;
            var outPutPropertyDic = init.OutPutPropertyInfos;
            Dictionary<string, IDMContext> dmContextDic = GetQueryContext(init);
            foreach (var source in sources)
            {
                var outPutObj = convertFunc == null ? new TResult() : convertFunc(source);
                if (copy)
                    FastCopy.Copy(source, outPutObj, false);
                var propertieResults = typeof(TResult).GetProperties();
                foreach (var propertieResult in propertieResults)
                {
                    var propertieName = propertieResult.Name;
                    if (!outPutPropertyDic.ContainsKey(propertieName))
                        continue;
                    var propertyName = outPutPropertyDic[propertieName].PropertySetName;
                    var sourceinfo = sourcePutPropertyDic.FirstOrDefault(x => x.Value.PropertySetName == propertyName).Key;
                    if (sourceinfo == null)
                        continue;
                    PropertyInfo? property = typeof(TSource).GetProperty(sourceinfo);
                    if (!dmContextDic.ContainsKey(propertieName))
                        continue;
                    var sourceValue = property?.GetValue(source);
                    if (sourceValue == null)
                        continue;
                    dmContextDic[propertieName].SetValue(outPutObj, propertieResult, sourceValue);
                }
                result.Add(outPutObj);
            }
            return result;
        }

        private static Dictionary<string, IDMContext> GetQueryContext(InitInfo init)
        {
            var dmContextDic = new Dictionary<string, IDMContext>();
            foreach (var outPutProperty in init.OutPutPropertyInfos)
            {
                var propertyName = outPutProperty.Value.PropertySetName;
                var sourceinfo = init.SourcePropertyInfos.FirstOrDefault(x => x.Value.PropertySetName == propertyName).Key;
                if (sourceinfo == null)
                    continue;
                var dmContext = QueryFactory.GetInstance()?.CreateContext(propertyName, init);
                if (dmContext != null)
                    dmContextDic.Add(outPutProperty.Key, dmContext);
            }
            return dmContextDic;
        }

        /// <summary>
        /// 基于特性属性自动赋值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="S"></typeparam>
        /// <param name="lists"></param>
        /// <param name="convertT"></param>
        /// <returns></returns>
        public static List<TResult> AutoFieldMapper<TSource, TResult>(this List<TSource> sources,
            Action<TSource, TResult>? convertAction = null,
            bool copy = true)
            where TSource : class
            where TResult : class, new()
        {




            return new List<TResult>();
        }
    }
}
